// OSR b JVCS

package org.jvcs.common;

import org.jvcs.client.core.*;
import org.jvcs.common.*;
import org.jvcs.utils.*;

import java.io.*;
import java.net.*;
import java.util.*;

// Begin program
public class baseCS {
	
	// Ini file of Global/Common/local/this-jvcs
	public static INIFile gini = new INIFile();
	public static INIFile cini = new INIFile();
	public static INIFile lini = new INIFile();
	public static INIFile tini = new INIFile();
	
	// Read Values
	public static String PROG_NAME = "";
	
	// Global Values
	public static String key = "";
	public static String value = "";
	public static String section = "";
	
	// INI File actual path set, after initializations
	public static String GlobalINIFile = "";
	public static String CommonINIFile = "";
	public static String LocalINIFile = "";
	public static String ThisINIFile = "";
	
	
	// ============================================================================== //
	
	// HELPERS: checkConf
	public static String checkConf (INIFile mini, String section, String key) {
		String op = null;
		try {
			if (section != null) {
				op = mini.getProperty(section, key);
			} else {
				op = mini.getProperty(key);
			}
		} catch (Exception e) {
			Utils.display("Error: checkConf => "+e.toString());
		}
		return op;
	}
	
	
	// HANDLERS: create
	public static void createHubHandler() {
		int argsLength = CmdLine.argAL.size();
		if (CmdLine.verboseFlag) osr.pl("CreateHubHandler Args: "+argsLength);
		if (argsLength != 2) { osr.pl(osr.gm(gini, G.U_usage, G.U_create)); osr.e();}	
		String action = null;
		String cdir = null;
		String site = null;
		if (argsLength == 2) {
			action = CmdLine.argAL.get(0);
			cdir = CmdLine.argAL.get(1);
			if (action.equalsIgnoreCase(G.S_hub)) {
				resolveSectionKey(cdir);
				if (CmdLine.verboseFlag) osr.pl("Dir for Hub given: "+cdir);
				// we got the hub details for creation from user; 1. check from ini 2. allow for direct usage
				site = checkConf(tini, section, key);
				if (site != null) {
					site = expandVar(tini, site);
				} else {
					site = cdir;
				}
				if (site.startsWith(G.PROTOCOL)) {
					if (CmdLine.verboseFlag) osr.pl("Network Path: "+site);
					String sh = null;
					int sp = G.DEFAULT_PORT;
					site = site.replace(G.PROTOCOL+G.PROTOCOL_START, "");
					String [] t1 = site.split("/");
					if (t1.length == 2) {
						sh = t1[0];
						String [] t2 = sh.split(":");
						if (t2.length == 2) {
							sh = t2[0];
							sp = Integer.parseInt(t2[1]);
							osrBuilder osb = new osrBuilder();
							if (CmdLine.verboseFlag) osr.pl("Connecting to Host: "+sh+"@"+sp);
							osb.createNetworkHub(sh, sp, site);
							
						} else {
							osr.ee("Unable to get the serverPort:"+site);
						}
						
					} else {
						osr.ee("Unable to get the serverHost:"+t1[0]);
					}
				} else {
					if (CmdLine.verboseFlag) osr.pl("File Path: "+site);
					osrBuilder osb = new osrBuilder();
					osb.createFileSystemHub();
				}
			}
		}
	}
	public static void createProjectHandler() {
		int argsLength = CmdLine.argAL.size();
		if (CmdLine.verboseFlag) osr.pl("CreateProjectHandler Args: "+argsLength);
		if (argsLength != 2) { osr.pl(osr.gm(gini, G.U_usage, G.U_create)); osr.e();}	
		String action = null;
		String cdir = null;
		String site = null;
		if (argsLength == 2) {
			action = CmdLine.argAL.get(0);
			cdir = CmdLine.argAL.get(1);
			if (action.equalsIgnoreCase(G.S_project)) {
				resolveSectionKey(cdir);
				if (CmdLine.verboseFlag) osr.pl("Dir for Hub given: "+cdir);
				// we got the hub details for creation from user; 1. check from ini 2. allow for direct usage
				site = checkConf(tini, section, key);
				if (site != null) {
					site = expandVar(tini, site);
				} else {
					site = cdir;
				}
				if (site.startsWith(G.PROTOCOL)) {
					if (CmdLine.verboseFlag) osr.pl("Network Path: "+site);
					String sh = null;
					int sp = G.DEFAULT_PORT;
					site = site.replace(G.PROTOCOL+G.PROTOCOL_START, "");
					String [] t1 = site.split("/");
					if (t1.length == 3) {
						sh = t1[0];
						String [] t2 = sh.split(":");
						if (t2.length == 2) {
							sh = t2[0];
							sp = Integer.parseInt(t2[1]);
							osrBuilder osb = new osrBuilder();
							if (CmdLine.verboseFlag) osr.pl("Connecting to Host: "+sh+"@"+sp);
							osb.createNetworkProject(sh, sp, site);
							
						} else {
							osr.ee("Unable to get the serverPort:"+site);
						}
						
					} else {
						osr.ee("Unable to get the serverHost:"+t1[0]);
					}
				
				} else {
					if (CmdLine.verboseFlag) osr.pl("File Path: "+site);
					osrBuilder osb = new osrBuilder();
					osb.createFileSystemHub();
				}
			}
		}
	}
	
	public static void createTaskHandler() {
		int argsLength = CmdLine.argAL.size();
		if (CmdLine.verboseFlag) osr.pl("CreateTaskHandler Args: "+argsLength);
	
	}
	public static void createIssueHandler() {
		int argsLength = CmdLine.argAL.size();
		if (CmdLine.verboseFlag) osr.pl("CreateIssueHandler Args: "+argsLength);
	
	}
	public static void createReleaseHandler() {
		int argsLength = CmdLine.argAL.size();
		if (CmdLine.verboseFlag) osr.pl("CreateReleaseHandler Args: "+argsLength);
	
	}
	public static void createBuildHandler() {
		int argsLength = CmdLine.argAL.size();
		if (CmdLine.verboseFlag) osr.pl("CreateBuildHandler Args: "+argsLength);
	
	}
	public static void createBranchHandler() {
		int argsLength = CmdLine.argAL.size();
		if (CmdLine.verboseFlag) osr.pl("CreateBranchHandler Args: "+argsLength);
	
	}
	public static void createTagHandler() {
		int argsLength = CmdLine.argAL.size();
		if (CmdLine.verboseFlag) osr.pl("CreateTagHandler Args: "+argsLength);
	
	}
	public static void createUserHandler() {
		int argsLength = CmdLine.argAL.size();
		if (CmdLine.verboseFlag) osr.pl("CreateUserHandler Args: "+argsLength);
		if (argsLength != 4) { osr.pl(osr.gm(gini, G.U_usage, G.U_create)); osr.e();}	
		String action = null;
		String userDetails = null;
		String nws = null;
		String site = null;
		String gr = null;
		if (argsLength == 4) {
			action = CmdLine.argAL.get(0);
			userDetails = CmdLine.argAL.get(1);
			gr = CmdLine.argAL.get(2);
			if (!gr.equalsIgnoreCase("in")) {osr.pl(osr.gm(gini, G.U_usage, G.U_create)); osr.e();}	
			nws = CmdLine.argAL.get(3);
			if (action.equalsIgnoreCase(G.S_user)) {
				resolveSectionKey(nws);
				if (CmdLine.verboseFlag) osr.pl("N/W URL for User given: "+nws);
				// we got the hub details for creation from user; 1. check from ini 2. allow for direct usage
				site = checkConf(tini, section, key);
				if (site != null) {
					site = expandVar(tini, site);
				} else {
					site = nws;
				}
				if (site.startsWith(G.PROTOCOL)) {
					if (CmdLine.verboseFlag) osr.pl("Network Path: "+site);
					String sh = null;
					int sp = G.DEFAULT_PORT;
					site = site.replace(G.PROTOCOL+G.PROTOCOL_START, "");
					
						sh = site;
						String [] t2 = sh.split(":");
						if (t2.length == 2) {
							sh = t2[0];
							sp = Integer.parseInt(t2[1]);
							osrBuilder osb = new osrBuilder();
							if (CmdLine.verboseFlag) osr.pl("Connecting to Host: "+sh+"@"+sp);								
							
							String userName = null;
							String passwd = null;
							String group = null;
							String ps = ":";
							String gs = "@";
							
							
								int pc = userDetails.indexOf(ps);
								int gc = userDetails.indexOf(gs);
								if (gc > 0) {
									String [] tmp = userDetails.split(gs);
									userName = tmp[0];
									group = tmp[1];
								} else {
									osr.ee("You need to provide the user with group name. e.g., create user user1@group1");
								}
								if (pc > 0) {
									String [] tmp = userName.split(ps);
									userName = tmp[0];
									passwd = tmp[1];
								} 		
							
							osb.createNetworkUser(sh, sp, userDetails);
							
						} else {
							osr.ee("Unable to get the serverPort: "+site);
						}
					
				
				} else {
					if (CmdLine.verboseFlag) osr.pl("File Path: "+site);
					osrBuilder osb = new osrBuilder();
					osb.createFileSystemUser();
				}
			}
		}
		
			
		
	
	}
	public static void createGroupHandler() {
		int argsLength = CmdLine.argAL.size();
		if (CmdLine.verboseFlag) osr.pl("CreateGroupHandler Args: "+argsLength);
	
	}
	// HANDLERS
	public static void DumpHandler() {
		if (CmdLine.verboseFlag) osr.pl("DumpHandler");
		int argsLength = CmdLine.argAL.size();
		String selectINI = null;
		String refINI = "all";
		if (argsLength > 0) {
			selectINI = CmdLine.argAL.get(0);
			if (selectINI.equalsIgnoreCase(G.THIS)) {
				refINI = G.THIS;
				dumpVar(tini);
			}
			if (selectINI.equalsIgnoreCase(G.LOCAL)) {
				refINI = G.LOCAL;
				dumpVar(lini);
			}
			if (selectINI.equalsIgnoreCase(G.COMMON)) {
				refINI = G.COMMON;
				dumpVar(cini);
			}
			if (selectINI.equalsIgnoreCase(G.GLOBAL)) {
				refINI = G.GLOBAL;
				dumpVar(gini);
			}
			if (selectINI.equalsIgnoreCase(G.ALL)) {
				refINI = G.ALL;
				dumpVar(gini);
				dumpVar(cini);
				dumpVar(lini);
				dumpVar(tini);
			}
			
		}
	}
	
	public static void GetHandler() {
		if (CmdLine.verboseFlag) osr.pl("GetHandler"); 
		// can the get,set, unset kv pair separation optimized further into generic server/client invoke
					int argsLength = CmdLine.argAL.size();
					if (argsLength == 1) {
						String arg1 = CmdLine.argAL.get(0);
						//Utils.display("Get Command Given "+arg1);
						key = arg1;
						int s1 = key.indexOf(".");
						if (s1 > 0) {									
							String [] skPair = key.split("\\.");
							if (skPair.length > 1) {									
								section = skPair[0];
								key = key.substring(s1+1, key.length());
								getCmd(tini, section, key);
							}
						} else {	
							getCmd(tini, null, key);							
						}
										
					} else {
						osr.ee("Usage: "+PROG_NAME+" get [section].key ");
					}
	}
	public static void UnsetHandler() {
		if (CmdLine.verboseFlag) osr.pl("UnsetHandler");	
		int argsLength = CmdLine.argAL.size();
					if (argsLength == 1) {
						String arg1 = CmdLine.argAL.get(0);
						key = arg1;
						int s1 = key.indexOf(".");
						if (s1 > 0) {									
							String [] skPair = key.split("\\.");
								if (skPair.length == 2) {									
									section = skPair[0];
									key = key.substring(s1+1, key.length());
									unsetCmd(tini, ThisINIFile, section, key);
								}
							} else {	
								unsetCmd(tini, ThisINIFile, null, key);							
							}
						
					} else {
						osr.ee("Usage: "+PROG_NAME+" unset [section].key ");
					}
	}
	public static void SetHandler() {
		if (CmdLine.verboseFlag) osr.pl("SetHandler");
					int argsLength = CmdLine.argAL.size();
					String refValue = "";
					if (CmdLine.verboseFlag) osr.pl("Args Length: "+argsLength);
					if (argsLength == 1) {
						String arg1 = CmdLine.argAL.get(0);
						String [] kvPair = arg1.split("=");
						if (kvPair.length == 2) {
							key = kvPair[0];
							value = kvPair[1];
							int s1 = key.indexOf(".");
							if (s1 > 0) {									
								String [] skPair = key.split("\\.");
								if (skPair.length > 1) {									
									section = skPair[0];
									key = key.substring(s1+1);
									// Check if already existing key=value is trying to be set
									refValue = tini.getProperty(section, key);
									if (refValue != null) 
										refValue = Utils.stdPath(refValue);
									if (value.equals(refValue)) {
										if (CmdLine.verboseFlag) osr.pl("Existing key=value: \n"+key+"="+value+"\nNew key=value\n"+key+"="+refValue);
										osr.ee("Same value");										
									}
									// new key=value
									setCmd(tini, ThisINIFile, section, key, value);
								}
							} else {
								refValue = tini.getProperty(key);
								if (refValue != null) 
									refValue = Utils.stdPath(refValue);
								if (value.equals(refValue)) {
									if (CmdLine.verboseFlag) osr.pl("Existing key=value: \n"+key+"="+value+"\nNew key=value\n"+key+"="+refValue);
									osr.ee("Same value");										
								}
								setCmd(tini, ThisINIFile, null, key, value);	
							}	
						
						} else {
							osr.ee("Usage of key=value syntax of the 'set' command.");
						}
					} else {
						Utils.display("Usage: "+PROG_NAME+" set [section].key=value ");
						System.exit(-1);
					}
	}
	
	
	// SET, UNSET, GET, DUMP
	public static void  getCmd (INIFile mini, String section, String key) {		
		try {
			if (section != null) {
				value = mini.getProperty(section, key);
			} else {
				value = mini.getProperty(key);
			}
			if (value != null) {
				osr.pl(""+value);
			} else {
				osr.ee("No variable found.");
			}
			String checkVar = expandVar(mini, value);
			
			int s2 = checkVar.indexOf("{");
			if (s2 == 0) {
				osr.pl(checkVar);
				osr.ee("Variable given is incorrect. Please check the spelling and definition.");			
			} else { 
				checkVar = Utils.stdPath(checkVar); 
				value = Utils.stdPath(value); 
				if (!checkVar.equals(value)) osr.pl(checkVar); 
			}
			
		} catch (Exception e) {
			osr.ee("getCmd => "+e.toString());
		}

	}
	public static void  unsetCmd (INIFile mini, String miniFile, String section, String key) {		
		try {
			if (section != null) {
				mini.deleteProperty(section, key);
			} else {
				mini.deleteKey(key);
			}
			mini.writeToFile(miniFile);			
		} catch (Exception e) {
			osr.ee("unsetCmd => "+e.toString());
		}
	}
	public static void  dumpVar (INIFile mini) {
		try {
			mini.dump(System.out);
		} catch (Exception e) {
			osr.ee("Error: dumpVar => "+e.toString());
		}
	}
	public static void setCmd (INIFile mini, String miniFile, String section, String key, String value) {		
		try {	
			// Process the Input given
			if (section != null) {
				mini.setProperty(section, key, value);
			} else {
				mini.setProperty(key, value);
			}
			mini.writeToFile(miniFile);		
			String checkExpansion = expandVar(mini, value);
			if (checkExpansion.indexOf("{") != -1 || checkExpansion.indexOf("{") != -1	) {
				if (CmdLine.verboseFlag) osr.pl("Expanded Variable: "+checkExpansion);
				osr.ee("Variable expansion failed. Check your declarations.");
			}
		} catch (Exception e) {
			osr.ee("setCmd => "+e.toString());
		}
	}
	public static String expandVar(INIFile mini, String inVar) {
		inVar = Utils.stdPath(inVar);
		String osrVar = inVar;
		if (CmdLine.verboseFlag) osr.pl("INCOMING: "+osrVar);
		int sp = osrVar.indexOf("{");
		int lp = osrVar.indexOf("}");
		
		if ( (sp != -1 ) || (lp != -1) ) {			
			String eVar = osrVar.substring(sp+1, lp);
			String oVar = osrVar.substring(sp, lp+1);
			resolveSectionKey(eVar);
			if (section != null) {
				value = mini.getProperty(section, key);
			} else {
				value = mini.getProperty(key);
			}
			if (value != null) {
				osrVar = osrVar.replace(oVar, value);
				if (CmdLine.verboseFlag) osr.pl("REPLACED: "+osrVar);
				osrVar = expandVar(mini, osrVar);
			}	
		} 	else {
			if (CmdLine.verboseFlag) osr.pl("RETURNING: "+osrVar);
			return osrVar;
		}
		return osrVar;
	}
	public static void resolveSectionKey(String inVar) {	
		// Set the global value
		int s1 = inVar.indexOf(".");
		if ( s1 > 0) {									
			String [] skPair = inVar.split("\\.");
			if (skPair.length > 1) {									
				section = skPair[0];
				key = inVar.substring(s1+1);				
			}
		} else {	
			section = null;
			key = inVar;
		}	
	}
	
	// HELP: for the client
	public static void helpBasicUsage() {
		if (CmdLine.versionFlag) {
			osr.pl(gini.getProperty(G.PROGRAM_DISPLAY, G.NAME) + " " +gini.getProperty(G.PROGRAM_DISPLAY, G.VERSION));
		}
		if (CmdLine.helpFlag && !CmdLine.helpCmdFlag) {
			osr.pl(gini.getProperty(G.PROGRAM_DISPLAY, G.HELP) );
		}
		if (CmdLine.helpFlag && CmdLine.helpCmdFlag) {
			String hc = gini.getProperty(G.HELP, CmdLine.helpCmd);
			if (hc != null) 
				osr.pl(""+ hc);
			else 
				osr.pl(CmdLine.helpCmd+ " command not found.");
		}
	}
	public static void helpDisplayDebug() {
		if (CmdLine.commentFlag) {
			osr.pl("Comments * :"+CmdLine.comments);
		}
		if (CmdLine.cmd != "") {
			osr.pl("Command: "+CmdLine.cmd);
		}
		for(int i=0;i<CmdLine.optAL.size();i++) {
			osr.pl("Option: "+CmdLine.optAL.get(i));
		}
		for(int i=0;i<CmdLine.argAL.size();i++) {
			osr.pl("Arg: "+CmdLine.argAL.get(i));
		}
	}

	
}